package cc.unitmesh.devins.ui.compose.sketch

import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextLinkStyles
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp
import com.mikepenz.markdown.compose.LocalMarkdownTypography
import com.mikepenz.markdown.compose.MarkdownElement
import com.mikepenz.markdown.compose.components.CurrentComponentsBridge
import com.mikepenz.markdown.compose.components.MarkdownComponents
import com.mikepenz.markdown.compose.components.markdownComponents
import com.mikepenz.markdown.compose.elements.MarkdownCodeFence
import com.mikepenz.markdown.compose.elements.MarkdownHighlightedCode
import com.mikepenz.markdown.compose.elements.MarkdownHighlightedCodeBlock
import com.mikepenz.markdown.m3.Markdown
import com.mikepenz.markdown.model.DefaultMarkdownTypography
import com.mikepenz.markdown.model.State
import dev.snipme.highlights.Highlights
import dev.snipme.highlights.model.SyntaxThemes
import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.decodeToImageBitmap
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi

/**
 * WASM 平台的 Markdown Sketch 渲染器实现
 * 使用 Compose + multiplatform-markdown-renderer
 * Mermaid 图表使用 Kroki 云端渲染
 */
actual object MarkdownSketchRenderer {
    @Composable
    actual fun RenderMarkdown(
        markdown: String,
        isComplete: Boolean,
        isDarkTheme: Boolean,
        modifier: Modifier
    ) {
        val isSystemDark = isSystemInDarkTheme()
        val highlightsBuilder = remember(isSystemDark) {
            Highlights.Builder().theme(SyntaxThemes.atom(darkMode = isSystemDark))
        }

        val typography = DefaultMarkdownTypography(
            h1 = MaterialTheme.typography.headlineMedium,
            h2 = MaterialTheme.typography.headlineSmall,
            h3 = MaterialTheme.typography.titleLarge,
            h4 = MaterialTheme.typography.titleMedium,
            h5 = MaterialTheme.typography.titleSmall,
            h6 = MaterialTheme.typography.labelLarge,
            text = MaterialTheme.typography.bodyMedium,
            code = MaterialTheme.typography.bodySmall.copy(fontFamily = FontFamily.Monospace),
            quote = MaterialTheme.typography.bodyMedium.copy(fontStyle = FontStyle.Italic),
            paragraph = MaterialTheme.typography.bodyMedium,
            ordered = MaterialTheme.typography.bodyMedium,
            bullet = MaterialTheme.typography.bodyMedium,
            list = MaterialTheme.typography.bodyMedium,
            table = MaterialTheme.typography.bodyMedium,
            inlineCode = MaterialTheme.typography.bodySmall.copy(fontFamily = FontFamily.Monospace),
            textLink = TextLinkStyles(
                style = SpanStyle(color = MaterialTheme.colorScheme.primary)
            )
        )

        Column(modifier = modifier) {
            Markdown(
                markdown,
                modifier = Modifier.fillMaxWidth(),
                typography = typography,
                components = markdownComponents(
                    heading1 = CurrentComponentsBridge.heading3,
                    heading2 = CurrentComponentsBridge.heading4,
                    heading3 = CurrentComponentsBridge.heading5,
                    heading4 = CurrentComponentsBridge.heading6,
                    heading5 = CurrentComponentsBridge.heading6,
                    codeBlock = {
                        MarkdownHighlightedCodeBlock(
                            content = it.content,
                            node = it.node,
                            highlightsBuilder = highlightsBuilder,
                            showHeader = true,
                        )
                    },
                    codeFence = {
                        val style = LocalMarkdownTypography.current.code
                        MarkdownCodeFence(it.content, it.node, style) { code, language, style ->
                            // Render Mermaid diagrams using remote Kroki service
                            MarkdownHighlightedCode(
                                code = code,
                                language = language,
                                style = style,
                                highlightsBuilder = highlightsBuilder,
                                showHeader = true,
                            )

                            if (language?.lowercase() == "mermaid" && isComplete) {
                                cc.unitmesh.viewer.web.MermaidRenderer(
                                    mermaidCode = code,
                                    modifier = Modifier.fillMaxWidth().heightIn(min = 200.dp)
                                )
                            }
                        }
                    },
                ),
                success = { state, components, modifier ->
                    MarkdownSuccess(state, components, modifier)
                },
            )

            if (!isComplete) {
                LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
            }
        }
    }

    @Composable
    actual fun RenderResponse(content: String, isComplete: Boolean, isDarkTheme: Boolean, modifier: Modifier) {
        val scrollState = rememberScrollState()

        // 自动滚动到底部
        LaunchedEffect(content) {
            if (content.isNotEmpty()) {
                scrollState.animateScrollTo(scrollState.maxValue)
            }
        }

        Column(
            modifier = modifier
                .verticalScroll(scrollState)
                .padding(16.dp)
        ) {
            RenderMarkdown(content, isComplete, isDarkTheme, Modifier.fillMaxWidth())
        }
    }

    @Composable
    actual fun RenderPlainText(text: String, modifier: Modifier) {
        Text(
            text = text,
            modifier = modifier.padding(16.dp),
            style = MaterialTheme.typography.bodyMedium
        )
    }
}

@Composable
fun MarkdownSuccess(
    state: State.Success,
    components: MarkdownComponents,
    modifier: Modifier = Modifier,
) {
    Column(modifier) {
        state.node.children.forEach { node ->
            MarkdownElement(node, components, state.content)
        }
    }
}

@OptIn(ExperimentalEncodingApi::class, ExperimentalResourceApi::class)
@Composable
fun RemoteMermaidRenderer(
    mermaidCode: String,
    modifier: Modifier = Modifier
) {
    var imageBitmap by remember { mutableStateOf<androidx.compose.ui.graphics.ImageBitmap?>(null) }
    var isLoading by remember { mutableStateOf(true) }
    var error by remember { mutableStateOf<String?>(null) }

    LaunchedEffect(mermaidCode) {
        isLoading = true
        error = null
        try {
            val base64Code = Base64.UrlSafe.encode(mermaidCode.encodeToByteArray())
            val url = "https://kroki.io/mermaid/png/$base64Code"

            // Use withTimeout to prevent hanging if Kroki server is down
            kotlinx.coroutines.withTimeout(10000L) { // 10 second timeout
                val client = HttpClient {
                    // Configure request timeout
                    install(io.ktor.client.plugins.HttpTimeout) {
                        requestTimeoutMillis = 8000 // 8 second request timeout
                        connectTimeoutMillis = 5000 // 5 second connection timeout
                        socketTimeoutMillis = 8000  // 8 second socket timeout
                    }
                }

                try {
                    val response: HttpResponse = client.get(url)
                    val bytes = response.readBytes()

                    // Decode PNG bytes to ImageBitmap
                    // Note: decodeToImageBitmap is from compose-resources
                    imageBitmap = bytes.decodeToImageBitmap()
                } finally {
                    client.close()
                }
            }
        } catch (e: kotlinx.coroutines.TimeoutCancellationException) {
            error = "Rendering timeout: Kroki service might be unavailable or slow"
        } catch (e: Exception) {
            error = "Failed to render diagram: ${e.message ?: "Unknown error"}"
        } finally {
            isLoading = false
        }
    }

    Box(
        modifier = modifier.background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.1f)),
        contentAlignment = Alignment.Center
    ) {
        if (isLoading) {
            CircularProgressIndicator()
        } else if (error != null) {
            Column(horizontalAlignment = Alignment.CenterHorizontally) {
                Text("Error rendering diagram", color = MaterialTheme.colorScheme.error)
                Text(error ?: "", style = MaterialTheme.typography.bodySmall)
                Text(mermaidCode, fontFamily = FontFamily.Monospace, modifier = Modifier.padding(8.dp))
            }
        } else {
            imageBitmap?.let { bitmap ->
                Image(
                    bitmap = bitmap,
                    contentDescription = "Mermaid Diagram",
                    contentScale = ContentScale.FillWidth,
                    modifier = Modifier.fillMaxWidth()
                )
            }
        }
    }
}
